﻿/// <reference path="../../config.ts" />
import ko = require("knockout")
import Track = require("Track");
import Editor = require("Editor");
import Clip1 = require("../../Clip");

const LoadingType = "_Loading";
const MaxTileWidth = 800;
const MinTileWidth = 400;

class Clip {
    public constructor(public params: {clip: Clip1, track: Track, editor: Editor, offset: number}) {
        this.clip = params.clip;
        this.track = params.track;
        this.editor = params.editor;
        this.tiles = ko.observableArray([]);
        this.style = ko.pureComputed(() => {
            var style = {
                msGridColumns: "",
                transformOrigin: this.holdOrigin(),
                left: params.offset * this.editor.zoom() + 'px',
                width: this.clip.duration() * this.editor.zoom() + 'px'
            };
            for (let i = 0; i < this.columnCount(); i++) {
                style.msGridColumns += " 1fr";
            }
            return style;
        });
        this.previousWidth = 0;

        // observables to redraw tiles
        var delayZoomTimer = null;
        var delayCheckRedraw = () => {
            if (delayZoomTimer) {
                clearTimeout(delayZoomTimer);
            }
            delayZoomTimer = setTimeout(() => {
                delayZoomTimer = null;
                this.checkRedrawTiles(this.editor.zoom());
            }, 50);
        };

        this.editor.zoom.subscribe(delayCheckRedraw);
        this.clip.type.subscribe(delayCheckRedraw);

        this.clip.streamCounter.subscribe(this.redrawTiles);

        this.redrawTiles();
    }

    isLoading: KnockoutComputed<boolean> = ko.pureComputed(() => this.clip.type()==LoadingType);

    public onTap = () => {
        this.editor.focusClip(this.clip);
    }

    public onHold = (args: {x:number, y:number}) => {
        this.held(true);
        this.holdOrigin(args.x + "px " + args.y + "px");
        this.editor.dragGrabOffset(args.x/this.editor.zoom());
    }

    public onDrag = () => {
        this.editor.dragClip(this.clip);
    }

    public onRelease = () => {
        this.held(false);
        this.editor.dragClip(null);
    }

    public onReleaseDrag = () => {
        if (this.editor.dragCanDrop()) {
            this.clip.move(this.editor.dragTargetTrack(), this.editor.dragTargetTime());
        }
        this.held(false);
        this.editor.dragClip(null);
    }

    checkRedrawTiles = (zoom: number) => {
        if (this.isLoading() || !this.clip.isAudio()) return;

        var width = this.clip.duration() * zoom;

        if (width / this.previousWidth < 0.5
            || width / this.previousWidth > 2  ) {
            this.redrawTiles();
        }

    }

    redrawTiles = () => {
        //var scrollPos = this.editor.scrollPos();
        //var viewPortWidth = this.editor.viewportElem().getBoundingClientRect().width;
        var width = this.clip.duration() * this.editor.zoom();

        var newCount = Math.ceil(width / MaxTileWidth);
        var newStep = this.clip.duration() / newCount;

        var newTiles = [];
        var i: number;
        for (i = 0; i < newCount; i++) {
            newTiles[i] = {
                start: newStep * i,
                length: newStep,
                clip: this.clip.clip,
                style: { msGridColumn: i + 1 }
            };
        }

        this.columnCount(newCount);

        var style = { msGridColumns: "" };
        for (i = 0; i < newCount; i++) {
            style.msGridColumns += " 1fr";
        }
        this.tiles().forEach((tile) => {
            if (tile.cancelCallback) {
                tile.cancelCallback();
            }
        });
        this.tiles(newTiles);
        this.previousWidth = width;
    }

    track: Track;
    editor: Editor;
    clip: Clip1;
    tiles: KnockoutObservableArray<ITile>;
    style: KnockoutComputed<Object>;
    previousWidth: number;
    columnCount: KnockoutObservable<number> = ko.observable(0);
    held: KnockoutObservable<boolean> = ko.observable(false);
    holdOrigin: KnockoutObservable<string> = ko.observable("50% 50%");
}

export = Clip;